使用Unity开发多场景多人游戏 |
您所在的位置:网站首页 › unity 多场景切换 › 使用Unity开发多场景多人游戏 |
我将在本文中讲述我是如何使用unity创造一个多人多场景的3D应用的。我之所以没有把它称为“游戏”是因为我不想把这个应用变成一个射击、毁坏、赚钱或者是有其他游戏元素的地方。 那么这个应用的功能是:在有街道和建筑的3D场景中你可以直接与别人交流或者是在他们的家里留下信息。现在这很简单,但是将来我想加入语音、个性定制还有像学校、公司、组织或者会议大楼的不同类型的建筑。 开发须知 Unity是一个很棒的工具,你可以直接在3D场景中添加物体,还可以操作地形。每一个物体都可以加上不同的组件,这些组件可以是Unity本身已经存在的或是你自己实现的。在Unity中还有资源商店,你可以从资源商店中找到很多的3D物体和脚本。调试的部分也很有意思,运行程序时可以切换到场景视窗然后作出调整,结果会直接呈现在游戏窗口中。 我把Unity纳入考虑是因为我用.Net已经6年了,因此我很习惯用它。Unity也可以用Javascript开发,但是对我来说使用C#开发更容易。 网络 有许多关于Unity网络的文章,我不想对此太过深入,但是基本上总会有一个服务器负责处理应用之间的通信。可以选择应用中的一个作为服务器来处理服务器的操作,所有的客户端通过(RPC)远程程序调用与服务器通信。 Unity中的多场景多玩家 应用中现在有不同的街道,不同的建筑。因此用户可以到一条街道上与其他用户见面。因此我只需要把此用户的位置推送给在那条街道上的用户即可。那么,如何实现呢?Unity有NetworkView.group和SetLevelPrefix(),但是这没有帮我实现一个多场景多玩家的应用。这是最难实现的部分,因为我没有在任何地方找到如何在Unity中实现它。当然,你可以找到一些第三方插件。 Unity有NetworkView组件用来同步一个观察的组件。当所有玩家都在同一个场景中时这个组件可以用。但是当有很多的场景可以供玩家自由出入时,带有需要同步观察组件的NetworkView就不是一个好的选择了。因为NetworkView会把消息送给所有的场景。因此,第一件需要做的事情就是禁止NetworkView同步,用户只向处于相同场景中的用户发送同步消息。对于这个需求,服务器需要知道每一个玩家所处的场景。因此客户端的调用像下面的代码: 在客户端(将状态发送给服务器): void Update() { if (lastLocalPlayerPosition != localPlayerObject.transform.position || lastLocalPlayerRotation != localPlayerObject.transform.rotation) { networkView.RPC("ServerUpdatePlayerPosition", RPCMode.Server, lastLocalPlayerPosition, lastLocalPlayerRotation, level); } } 在服务器端(过滤玩家,只向在同一场景的玩家发送更新) [RPC] void ServerUpdatePlayerPosition(Vector3 pos, Quaternion rot, string level) { foreach (PlayerProperties player in server_OnlinePlayers.Values) { if (player.Level == level && player.NetworkPlayer != Network.Player) networkView.RPC("ClientUpdatePlayerPosition", player.NetworkPlayer, p, pos, rot); } } 在其他客户端: [RPC] void ClientUpdatePlayerPosition(NetworkPlayer p, Vector3 pos, Quaternion rot) { var thePlayer = FindPlayer(p); if ( thePlayer != null && thePlayer.GameObject != null) { var controller = thePlayer.GameObject.GetComponent(); controller.position = pos; controller.rotation = rot; } } 一些技巧 如何通过RPC调用发送定制物体 Unity不允许通过RPC发送定制物体,只有int/string/float/NetworkPlayer/NetworkViewID/Vector/Quaternation类型的物体才可以被传送。为了发送不同种类的物体,你需要把此物体序列化和反序列化。首先,我使用strings来存储,但是存在一个string中存储大于4096个char的问题。然后我发现Unity也接受bytes数组,因此我使用了这个特性。 比如我通过RPC调用发送了一个UserMessage类型的物体,此物的属性有:Date,UserId,Message,Type等等。这个是不可能实现的,因为这个物体是不会被接受的,因此我用下面的方法把它序列化: public static byte[] Byte_ConvertObjectToBinary(object obj) { MemoryStream o = new MemoryStream(); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(o, obj); return o.GetBuffer(); } 然后通过RPC调用发送: networkView.RPC("Server_NewMessageAdded", networkPlayer, Utils.Byte_ConvertObjectToBinary(userMessage )); 然后在客户端反序列化: public static object Byte_ReadFromBinary(byte[] data) { if (data == null || data.Length == 0) return null; var ins = new MemoryStream(data); BinaryFormatter bf = new BinaryFormatter(); return bf.Deserialize(ins); } 如何把一个定制的物体附着到一个游戏物体上 (如果那个物体不是MonoBehaviour的子类): 我把一个空物体加到一个有TextMesh的物体上,因此我把有文字数字能够的物体序列化为一个string,当我需要物体时,我把这个物体反序列化然后再使用。 免费的3D模型 这个应用我需要一些3D模型,但是我不是一个3D建模师,因此我需要一些免费的模型。Sketchup是一个很好的工具,你可以找到和创造很多3D模型。在Unity资源商店中有许多的免费模型。 结论 Windows/Linux//BlackBerry/iOS/WindowsPhone 8/unity /XBOX/Wii.使用Unity工作很好,对我来说这是一个制作3D游戏的新体验。Unity另外一个很好的地方是Unity可以被发布到如下平台: Windows/Linux/Android/BlackBerry/iOS/WindowsPhone 8/unity WebPlayer/XBOX/Wii。 原文链接:https://www.gamedev.net/resources/_/technical/multiplayer-and-network-programming/multilevel-multiplayer-with-unity-r3580 原文作者:Sorin Albu |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |